<template>
  <div>
    <div ref="demo1" @mousedown="mousedown"></div>
    <div ref="statsOutput"></div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { Stats } from 'three-stats'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// import { FontLoader } from 'three/examples/jsm/loaders/FontLoader'
import TWEEN from '@tweenjs/tween.js'

export default {
  data () {
    return {
      mouse: {}
    }
  },
  methods: {
    init () {
      this.initScene()
      this.initLight()
      this.initCamera()
      this.initRender()
      this.initController()
      this.initStats()
    },
    initScene () {
      this.scene = new THREE.Scene()
      // const scene = this.scene
      // const material = new THREE.LineBasicMaterial({ color: 0x0000ff })
      // const points = []
      // points.push(new THREE.Vector3(-10, 0, 0))
      // points.push(new THREE.Vector3(0, 10, 0))
      // points.push(new THREE.Vector3(10, 0, 0))

      // const geometry = new THREE.BufferGeometry().setFromPoints(points)

      // const line = new THREE.Line(geometry, material)
      // scene.add(line)

      this.loadBottle()
    },
    initLight () {
      const ambient = new THREE.AmbientLight(0xdddddd)
      this.scene.add(ambient)
    },
    initCamera () {
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500)
      const camera = this.camera
      camera.position.set(0, 0, 100)
      camera.lookAt(0, 0, 0)
    },
    initRender () {
      this.renderer = new THREE.WebGLRenderer({
        antialias: true
      })
      const renderer = this.renderer
      renderer.setSize(window.innerWidth, window.innerHeight)
      this.$refs.demo1.appendChild(renderer.domElement)
      // renderer.render(this.scene, this.camera)
      this.render()
    },
    render () {
      requestAnimationFrame(() => {
        this.render()
        TWEEN.update()
        this.stats.update()
      })
      this.renderer.render(this.scene, this.camera)
    },
    initController () {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    },
    initStats () {
      this.stats = new Stats()
      const stats = this.stats
      // 设置统计模式
      stats.setMode(0) // 0: fps, 1: ms
      // 统计信息显示在左上角
      stats.domElement.style.position = 'absolute'
      stats.domElement.style.left = '0px'
      stats.domElement.style.top = '0px'
      // 将统计对象添加到对应的<div>元素中
      this.$refs.statsOutput.appendChild(stats.domElement)
      return stats
    },
    loadBottle () {
      const loader = new GLTFLoader()
      loader.load('/model/simplebottle.glb', gltf => {
        this.box = gltf.scene
        this.scene.add(gltf.scene)
        gltf.scene.traverse(item => {
          if (item.name === '瓶身') {
            this.body = item
          } else if (item.name === '瓶盖') {
            this.head = item
            this.headOriginPosY = this.head.position.y
          }
          // console.log(item)
        })
        this.loadText()
      }, undefined, function (error) {
        console.error(error)
      })
    },
    loadText () {
      // const loader = new FontLoader()
      // loader.load('/font/STZhongsong_Regular.json', font => {
      //   const fontMaterial = new THREE.MeshLambertMaterial({
      //     color: 0x912cee,
      //     side: THREE.DoubleSide
      //   })
      //   const shapes = font.generateShapes('瓶盖', 0.5)
      //   const fontGeometry = new THREE.ShapeGeometry(shapes)
      //   this.newFont = new THREE.Mesh(fontGeometry, fontMaterial)
      //   this.newFont.position.x = 1.5
      //   this.newFont.position.y = this.headOriginPosY
      //   this.newFont.visible = false
      //   this.scene.add(this.newFont)
      // })
      const canvas = document.createElement('canvas')
      canvas.width = 100
      canvas.height = 60
      const ctx = canvas.getContext('2d')
      ctx.fillStyle = 'blue'
      ctx.fillRect(0, 0, canvas.width, canvas.height)
      ctx.fillStyle = 'red'
      ctx.font = 'bold 48px 宋体'
      console.log(ctx)
      ctx.fillText('瓶盖', 0, 50)
      const texture = new THREE.CanvasTexture(canvas)
      console.log(texture)
      document.body.appendChild(canvas)
      const spriteMaterial = new THREE.SpriteMaterial({
        color: 0xff00ff,
        map: texture
      })
      const sprite = new THREE.Sprite(spriteMaterial)
      sprite.scale.set(1, 0.6, 1)
      this.newFont = sprite
      this.newFont.position.x = 2
      this.newFont.position.y = this.headOriginPosY
      this.newFont.visible = false
      this.scene.add(this.newFont)
    },
    mousedown (event) {
      event.preventDefault()
      // console.log(this.box)
      if (!this.box) {
        return
      }

      const camera = this.camera
      const mouse = this.mouse
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
      const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(camera)
      const raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize())
      // console.log(this.scene.children)
      const intersects = raycaster.intersectObjects([this.box], true)

      if (intersects.length > 0) {
        // 选中第一个射线相交的物体
        const intersected = intersects[0].object
        if (intersected.name.indexOf('瓶盖') !== -1) {
          const position = this.head.position
          const duration = 500
          if (!this.head2Top) {
            this.head2Top = true
            if (this.head2BottomTween) {
              this.head2BottomTween.stop()
            }
            this.head2TopTween = new TWEEN.Tween(position).to({ y: 10 }, duration).onUpdate(pos => {
              this.head.rotation.y += 0.1
              this.newFont.position.y = pos.y
            }).onComplete(() => {
              this.newFont.visible = true
            }).start()
          } else {
            this.head2Top = false
            this.head2TopTween.stop()
            this.head2BottomTween = new TWEEN.Tween(position).to({ y: this.headOriginPosY }, duration).onUpdate(pos => {
              this.head.rotation.y -= 0.1
              this.newFont.position.y = pos.y
            }).onComplete(() => {
            }).start()
            this.newFont.visible = false
          }
        }
      }
    }
  },
  mounted () {
    this.init()
  }
}
</script>

<style>
  body {
    margin: 0;
  }
</style>
